/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

package chatsystem;
import chatsystem.patternState.OnlineState;
import chatsystem.patternState.OfflineState;
import chatsystem.patternObserver.Observable;
import chatsystem.patternObserver.Observer;
import java.util.ArrayList;
import javax.swing.DefaultListModel;
import protocol.TalkID;

/**
 *
 * @author remires
 */
public class ChatSystemModel extends DefaultListModel implements Observable {

    private User myself;  
    private ArrayList<User> users_connected;
    private ArrayList<Conversation> conversations;
    /* Mise en place du Pattern Observer */
    private ArrayList<Observer> listObserver = new ArrayList<Observer>();

    /* Mise en place du Pattern State */
    private Etat etat;

    public static abstract class Etat {

    /**
     * Méthode protégée permattant de changer l'état
     * @param pClasse
     * @param pEtat
     */
    protected void setEtat(ChatSystemModel pClasse, Etat pEtat) {
        pClasse.etat = pEtat;
    }

    // Méthodes pour changer d'état
    public abstract void operationEtatOffline(ChatSystemModel pClasse);
    public abstract void operationEtatOnline(ChatSystemModel pClasse);
    public abstract void operationEtatProcessUsersList(ChatSystemModel pClasse);

    // Affichage de l'état courant
    public abstract void afficherEtat();

    // Retourne l'état courant
    public abstract Etat getEtat();
}

    public ChatSystemModel() {
        super();
        this.etat = new OfflineState();   
        users_connected = new ArrayList<User>();
        conversations = new ArrayList<Conversation>();
    }
    
    public User getMySelf() {
        return myself;
    }
    
    public void setMySelf(User u) {
        this.myself = u;
    }
    
    public ArrayList<User> getUsersConnected() {
        return users_connected;
    }

    public void setUsersConnected(ArrayList<User> l) {
        users_connected = l;
    }
    
    public void resetListUsers() {
        this.users_connected = new ArrayList<User>();
    }
    
    public void addUser(User u) {
        users_connected.add(u);
        addElement(u.getName());
    }

    public void removeUser(User u) {
        removeElementAt(indexOf(u.getName()));
        users_connected.remove(u);        
    }
    
    public ArrayList<Conversation> getConversations() {
        return conversations;
    }

    public Conversation getConversationByID(TalkID id) {
        Conversation conversation = null;
        for (Conversation c : conversations) {
            if (c.getTid().equals(id)) conversation = c;
        }
        return conversation;
    }

    public void setConversations(ArrayList<Conversation> conversations) {
        this.conversations = conversations;
    }
    
    public void addConversation(Conversation c) {
        conversations.add(c);
    }  
    
    
    /*
     * Implémentation du Pattern Observer
     */
    public void addObserver(Observer obs) {
        this.listObserver.add(obs);
    }

    public void removeObserver() {
        listObserver = new ArrayList<Observer>();
    }

    public void notifyObserver(ChatSystemModel cs) {
       
        /* L'état a changé -> on notifie à la vue */
        System.out.println("L'état a changé, on notifie la vue");        
        for(Observer obs : listObserver) {
                obs.update(cs);
        }
    }

    /*
     * Implémentation du Pattern State
     */

    // Méthodes pour changer d'état
    public void operationEtatOffline() {
        etat.operationEtatOffline(this);
        etat.setEtat(this, new OfflineState());
        this.afficherEtat();
        this.notifyObserver(this);
    }

    public void operationEtatOnline() {        
        etat.operationEtatOnline(this);
        etat.setEtat(this, new OnlineState());
        this.afficherEtat();
        // L'état a changé, on notifie l'observer
        System.out.println("L'état a changé, on notifie l'observer");        
        this.notifyObserver(this);
    }

    /**
     * Affichage de l'état courant
     */
    public void afficherEtat() {
        etat.afficherEtat();
    }

    public Etat getEtat() {
        return this.etat;
    }
}
